#include <ioCC2530.h>               //引用 CC2530 头文件
#include <string.h>                 //引用新头文件，此头文件关系本次代码写法：uchar等等
#define SW1 P1_2                    //宏定义，如下是LED宏定义
#define LED1 (P1_0)                 //宏定义，LED1，简单好写。
#define LED2 (P1_1)                 //宏定义，LED2，简单好写.
#define DATABUFF_SIZE 3             //数据缓冲区大小，在第五单元PDF
#define uchar unsigned char
unsigned int t3_Count=0;            //定时器3溢出次数计数。
uchar buff_RxDat[DATABUFF_SIZE+1];
uchar chat = 0;                     //数据缓冲区 + 下标
unsigned char val_LEDn;
unsigned char val_LED_Speed;
                                    //控制LED速度，LEDn字符1、2，LED_SPEED：0~9
unsigned char LEDn;
unsigned char LED_Speed;

#pragma vector = T3_VECTOR
__interrupt void T3_INT(void)
{
  IRCON = 0x00;                     //清理中断标志，也可以通过硬件自清理。这一行去查看ioCC2530的Interrupt Flags 4
  t3_Count++;                       //t3，使用int整数型。
}


void initUART0(void)
{
  PERCFG=0x00;
  P0SEL=0x3c;                       //启动P0.2 P0.3 P0.4 P0.5作为外设IO口。第五单元PDF有详细介绍。
  U0CSR|=0x80;                      //11110000 UART mode+禁止接收器+SPI 从
  U0UCR|=0x80;                      //11110000 清除单元 +禁止流控制+奇校验+8位传送禁9位+1停止位低电平
  U0BAUD=216;                       //U0BAUD.BAUD_M = 216 
  U0GCR=10;                         //U0GCR.BAUD_M = 10 如上对应CC2530串行通信波特率 设置为57600 误差0.03%
  UTX0IF=0;                         //清零UART0TX中断标志
  EA = 1;                           //使能中断
  U0CSR |= 0x40;                    //允许接收,这句话尤其重要！
}

void receive_handler(void)
{
  unsigned char c;

  c = U0DBUF;                       //读取收取到的字节，unsigned char为无符号整数型，本次需要用到这类。而不是直接char。
                                    //         char         = -128~127
                                    //unsigned char = uchar = 0~255
                                    //c = USART 0 Receive/Transmit Data Buffer 在ioCC2530.h头文件Interrupt Flags 4
  if(c == '*')
  {
    buff_RxDat[0]=c;
    chat=0;
  }
  else if(buff_RxDat[0]=='*')
  {
    chat++;
    buff_RxDat[chat]=c;
  }
  if(chat>=2)
  { 
    val_LEDn= buff_RxDat[1];
    val_LED_Speed= buff_RxDat[chat]-'0';
    for(int i=0;i<=DATABUFF_SIZE;i++)
    {                               //清空接收到的字符串
      buff_RxDat[i]=(unsigned char)0;
      chat = 0;
    }
  }
}

void UART0SendByte(unsigned char c)
{
  U0DBUF = c;                       //将要发送的 1 字节数据写入 U0DBUF
  while (!UTX0IF);                  //等待 TX 中断标志，即 U0DBUF 就绪
  UTX0IF = 0;                       //清零 TX 中断标志
}

void UART0SendString(unsigned char *str)
{
  while(*str != '\0')
  {
    UART0SendByte(*str++);          //发送字节数据
  }
}

void initTimer1()
{
  CLKCONCMD &= 0x80;                //时钟速度设置为 32MHz
  T3CCTL0 =50000 & 0xFF;            //把 50000 的低 8 位写入 T3CCTL0 /*  Timer 3 Channel 0 Capture/Compare Control          */
  T3CC0 =((50000 & 0xFF00) >> 8);   //把 50000 的高 8 位写入 T3CC0   /*  Timer 3 Channel 0 Capture/Compare Value            */
  EA = 1;                           //使能全局中断
  T3CTL |= 0xE0;                    //定时器3 时钟频率128分频 设置最大计数值在此设置。
                                    //推一下我的计算方式吧，因为我这一次跟老师不一样。
                                    //首先，128分频,128/16000000*N=0.5S,N=62500
  T3IE = 1;                         //使能定时器3      总中断                                  
  T3CCTL0 |= 0x08;                  //使能定时器3通道1 溢出中断
  T3CCTL0 &= ~0x03;                 //定时器3通道1 采用 自由mode
                                    //00->0xff 62500/255=245次。此时245次为0.5秒。
  T3CTL |= 0x10;                    //启动 关键code 全局启动
}


extern void delay(unsigned int LED_Speed)
{

}

void LED_Flash(unsigned char LEDn,unsigned char LED_Speed)
{
  LED_Speed %=10;                  //求模且赋值运算符。相当于LED速度=LED速度/10
  if(LED_Speed)
  {
    LED_Speed=10-LED_Speed;        //上面的LED速度=LED速度/10，此时是10-(LED速度/10)，满足题意0熄灭1最慢9最快。
    delay(LED_Speed*200);
    switch(LEDn)                    
    {
      case '1':                     
        LED1=!LED1;
        break;                      
      case '2':                     
        LED2=!LED2;
        break;                      
    }
  }
  else
  {
    LED1=0;
    LED2=0;
  }
}

/***************************************************************************************************************
本次1.7.2021.0101.5-Unfinished版本，代码和写法均来自第五单元.pdf和CC2530中文数据手册完全版和头文件.
                                    第五单元.pdf                 
                                    ioCC2530.h                   C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.0\8051\bin
                                    ！！！本次版本为首次上线的未完工版本！！！
                                    因为很多的意外和特殊原因，其实这个要解决LED闪烁速度的版本，推迟了。
                                    尤其是delay函数的不确定性，直接导致了这样事情。
                                    但无论如何，我还是希望这个版本先迭代出来，做个备份。
                                    那么...这个版本就先这样吧。
                                    欢迎大家认真使用，本代码已经同步至GITEE仓库，遵守BY-NC-SA4.0协议，使用转载请署名。
***************************************************************************************************************/

void main(void) 
{
  /*LED1 LED2设置普通IO输出口完毕*/
  LED1 = 0;
  LED2 = 0;
  P1SEL &= ~0x03;                   //设置P1.0和P1.1为普通IO口。P1.0 P1.1为LED
  P1DIR |= 0x03;                    //设置P1.0和P1.1为输出口。  P1.0 P1.1为LED
  CLKCONCMD &= 0x80;                //时钟速度设置为 32MHz
  /*调用函数 initTimer1 initUART0 也已经完成初始化设置*/
  initTimer1();                     //初始化如上函数，EA全局使能中断可以在这里写。
  initUART0();                      //初始化如上上函数
  
  while(1)
  { 
    //设置发送已经设定好的数据,目前已经注释,无需使用**
    if(t3_Count>=1470)              //3秒，1秒=490
    {
      //LED1 = 1;
      UART0SendString("CC2530在线 ");
      //LED1 = 0;
      LED2 = 1;
      UART0SendString("CC2530working.\n");
      LED2 = 0;
      t3_Count = 0;
    }
    if(URX0IF)
    {
      URX0IF = 0;//清中断标志
      receive_handler(); //调用接收数据后处理函数
    }
    LED_Flash(val_LEDn,val_LED_Speed);
  }
}
